home *** CD-ROM | disk | FTP | other *** search
/ Point Programming 1 / PPROG1.ISO / pascal / swag / textfile.swg / 0045_Delete dupe lines.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-03-26  |  11.9 KB  |  315 lines

  1. Program Dup;
  2.    { delete duplicate lines from a sorted text file }
  3.    { Dup file1 file2 }
  4.  
  5. Uses
  6.   Dos;
  7.  
  8. Type
  9.   string3 = string[3];
  10. Const
  11.   WhiteSpace : string3 = #00#09#255;
  12.  
  13. Const
  14.   NoFAttr : word = $1C; { attributen dir, volume, system }
  15.   FAttr   : word = $23; { readonly-, hidden-, archive attributen }
  16.   BufSize = 16384;      { buffersize 16 KB }
  17.  
  18. Type
  19.   BufType = array [1..BufSize] of char;
  20.  
  21. Var
  22.   Fname1, Fname2   : string;
  23.   Line1, Line2     : string;
  24.   tmp1 , tmp2      : string;   { temporary vars for lower case comparing }
  25.   OldFile, NewFile : text;
  26.   OldBuf , NewBuf  : BufType;
  27.   tel              : longint;
  28.  
  29.  
  30. function OpenTextFile( var InF: text; name: string; var buffer: BufType ): boolean;
  31. begin
  32.   Assign( InF, Name );
  33.   SetTextBuf( InF, buffer );
  34.   Reset( InF );
  35.   OpenTextFile := ( IOResult = 0 );
  36. end { OpenTextFile };
  37.  
  38. function CreateTextFile( var OutF: text; name: string; var buffer: BufType ): boolean;
  39. begin
  40.   Assign( OutF, Name );
  41.   SetTextBuf( OutF, buffer );
  42.   Rewrite( OutF );
  43.   CreateTextFile := ( IOResult = 0 );
  44. end { CreateTextFile };
  45.  
  46.  
  47. function FileExist( var FName : string ) : Boolean;
  48.   {-Return true if entry is found and if it's a file}
  49. var
  50.   F    : file;
  51.   Attr : Word;
  52. begin
  53.   Assign( F, FName );
  54.   GetFAttr( F, Attr );
  55.   if DosError = 0 then
  56.     FileExist := ( ( Attr and NoFAttr ) = 0 )
  57.     { not dir-, volume- or system bit? }
  58.   else
  59.     FileExist := False;            { DosError }
  60.   {}
  61. end;
  62.  
  63.  
  64. procedure StrCopy( var Str1, Str2: string ); assembler;
  65.   { copy str1 to str2 }
  66. asm
  67.         LDS   SI,Str1    { load in DS:SI pointer to str1 }
  68.         CLD              { string operations forward     }
  69.         LES   DI,Str2    { load in ES:DI pointer to str2 }
  70.         XOR   CH,CH      { clear CH                      }
  71.         MOV   CL,[SI]    { length str1 --> CX            }
  72.         INC   CX         { include length byte           }
  73.     REP MOVSB            { copy str1 to str2             }
  74. end  { StrCopy };
  75.  
  76.  
  77. procedure Lower( var Str: String );
  78. { 52 Bytes by Bob Swart, 11-6-1993, FidoNet '80XXX' FASTEST! }
  79. InLine(
  80.   $8C/$DA/               {       mov   DX,DS                 }
  81.   $BB/Ord('A')/
  82.       Ord('Z')-Ord('A')/ {       mov   BX,'Z'-'A'/'A'        }
  83.   $5E/                   {       pop   SI                    }
  84.   $1F/                   {       pop   DS                    }
  85.   $FC/                   {       cld                         }
  86.   $AC/                   {       lodsb                       }
  87.   $88/$C1/               {       mov   CL,AL                 }
  88.   $30/$ED/               {       xor   CH,CH                 }
  89.   $D1/$E9/               {       shr   CX,1                  }
  90.   $73/$0B/               {       jnc   @Part1                }
  91.   $AC/                   {       lodsb                       }
  92.   $28/$D8/               {       sub   AL,BL                 }
  93.   $38/$F8/               {       cmp   AL,BH                 }
  94.   $77/$04/               {       ja    @Part1                }
  95.   $80/$44/$FF/
  96.       Ord('a')-Ord('A')/ {@Loop: ADD   Byte Ptr[SI-1],'a'-'A'}
  97.   $E3/$14/               {@Part1:jcxz  @Exit                 }
  98.   $AD/                   {       lodsw                       }
  99.   $28/$D8/               {       sub   AL,BL                 }
  100.   $38/$F8/               {       cmp   AL,BH                 }
  101.   $77/$04/               {       ja    @Part2                }
  102.   $80/$44/$FE/
  103.       Ord('a')-Ord('A')/ {       ADD   Byte Ptr[SI-2],'a'-'A'}
  104.   $49/                   {@Part2:dec   CX                    }
  105.   $28/$DC/               {       sub   AH,BL                 }
  106.   $38/$FC/               {       cmp   AH,BH                 }
  107.   $77/$EC/               {       ja    @Part1                }
  108.   $EB/$E6/               {       jmp   @Loop                 }
  109.   $8E/$DA                {@Exit: mov   DS,DX                 }
  110. ) { LowerFast };
  111.  
  112.  
  113. procedure White2Space( var Str: string; const WhiteSpace: string ); assembler;
  114.   { replace white space chars in Str by spaces
  115.     the string WhiteSpace contains the chars to replace }
  116. asm     { setup }
  117.         cld                      { string operations forwards    }
  118.         les   di, str            { ES:DI points to Str           }
  119.         xor   cx, cx             { clear cx                      }
  120.         mov   cl, [di]           { length Str in cl              }
  121.         jcxz  @exit              { if length of Str = 0, exit    }
  122.         inc   di                 { point to 1st char of Str      }
  123.         mov   dx, cx             { store length of Str           }
  124.         mov   bx, di             { pointer to Str                }
  125.         lds   si, WhiteSpace     { DS:SI points to WhiteSpace    }
  126.         mov   ah, [si]           { load length of WhiteSpace     }
  127.  
  128. @start: cmp   ah, 0              { more chars WhiteSpace left?   }
  129.         jz    @exit              { no, exit                      }
  130.         inc   si                 { point to next char WhiteSpace }
  131.         mov   al, [si]           { next char to hunt             }
  132.         dec   ah                 { ah counting down              }
  133.         xor   dh, dh             { clear dh                      }
  134.         mov   cx, dx             { restore length of Str         }
  135.         mov   di, bx             { restore pointer to Str        }
  136.         mov   dh, ' '            { space char                    }
  137. @scan:
  138.   repne scasb                    { the hunt is on                }
  139.         jnz   @next              { white space found?            }
  140.         mov   [di-1], dh         { yes, replace that one         }
  141. @next:  jcxz  @start             { if no more chars in Str       }
  142.         jmp   @scan              { if more chars in Str          }
  143. @exit:
  144. end  { White2Space };
  145.  
  146.  
  147. procedure RTrim( var Str: string ); assembler;
  148.   { remove trailing spaces from str }
  149. asm     { setup }
  150.         std                      { string operations backwards   }
  151.         les   di, str            { ES:DI points to Str           }
  152.         xor   cx, cx             { clear cx                      }
  153.         mov   cl, [di]           { length Str in cl              }
  154.         jcxz  @exit              { if length of Str = 0, exit    }
  155.         mov   bx, di             { bx points to Str              }
  156.         add   di, cx             { start with last char in Str   }
  157.         mov   al, ' '            { hunt for spaces               }
  158.  
  159.         { remove trailing spaces }
  160.    repe scasb                    { the hunt is on                }
  161.         jz    @null              { only spaces?                  }
  162.         inc   cx                 { no, don't lose last char      }
  163. @null:  mov   [bx], cl           { overwrite length byte of Str  }
  164. @exit:
  165. end  { RTrim };
  166.  
  167.  
  168. procedure LTrim( var Str: string ); assembler;
  169.   { remove leading spaces from str }
  170. asm     { setup }
  171.         cld                      { string operations forward          }
  172.         lds   si, str            { DS:SI points to Str                }
  173.         xor   cx, cx             { clear cx                           }
  174.         mov   cl, [si]           { length Str --> cl                  }
  175.         jcxz  @exit              { if length Str = 0, exit            }
  176.         mov   bx, si             { save pointer to length byte of Str }
  177.         inc   si                 { 1st char of Str                    }
  178.         mov   di, si             { pointer to 1st char of Str --> di  }
  179.         mov   al, ' '            { hunt for spaces                    }
  180.         xor   dx, dx             { clear dx                           }
  181.  
  182. @start: { look for leading spaces }
  183.    repe scasb                    { the hunt is on                     }
  184.         jz    @done              { if only spaces, we are done        }
  185.         inc   cx                 { no, don't lose 1st non-blank char  }
  186.         dec   di                 { no, don't lose 1st non-blank char  }
  187.         mov   dx, cx             { new lenght of Str                  }
  188.         xchg  di, si             { swap si and di                     }
  189.     rep movsb                    { move remaining part of Str         }
  190. @done:  mov   [bx], dl           { new length of Str                  }
  191. @exit:
  192. end  { LTrim };
  193.  
  194.  
  195. function LineOK( var str: string ) : Boolean; assembler;
  196.   { Line contains chars > ASCII 20h ? }
  197. asm     { setup }
  198.         xor   ax, ax         { assume false return value        }
  199.         xor   cx, cx         { clear cx                         }
  200.         lds   si, str        { load in DS:SI pointer to Str     }
  201.         mov   cl, [si]       { length Str --> cx                }
  202.         jcxz  @exit          { if no characters, exit           }
  203.         inc   si             { point to 1st character           }
  204.  
  205.         { look for chars > ASCII 20h }
  206. @start: mov   bl, [si]       { load character                   }
  207.         cmp   bl, ' '        { char > ASCII 20h?                }
  208.         ja    @yes           { yes, return true                 }
  209.         inc   si             { next character                   }
  210.         dec   cx             { count down                       }
  211.         jcxz  @exit          { if no more characters left, exit }
  212.         jmp   @start         { try again                        }
  213. @yes:   mov   ax, 1          { return value true                }
  214. @exit:
  215. end  { LineOK };
  216.  
  217.  
  218. procedure TestLine( var Line, tmp : string );
  219. var
  220.   len: byte absolute Line;
  221.  
  222.   procedure TrimLine;
  223.   begin
  224.     White2Space( Line, WhiteSpace );  { white space to spaces   }
  225.     RTrim( Line );                    { remove trailing spaces  }
  226.   end;
  227.  
  228.   procedure TrimPlus;
  229.   begin
  230.     TrimLine;
  231.     while Line[len] = '+' do
  232.     begin
  233.       dec( len );
  234.       TrimLine;
  235.     end;
  236.   end;
  237.  
  238. begin
  239.   TrimPlus;
  240.   while not Eof( OldFile ) and ( IOResult = 0 ) and ((length( Line ) = 0) or not LineOK( Line )) do
  241.   begin
  242.     ReadLn( OldFile, Line );
  243.     TrimPlus;
  244.   end;
  245.   StrCopy( Line, tmp );             { copy to temp string     }
  246.   LTrim( tmp );                     { remove leading spaces   }
  247.   Lower( tmp );                     { translate to lower case }
  248. end;  { TestLine }
  249.  
  250.  
  251. begin
  252.   if ParamCount > 1 then             { parameters file1 file2 }
  253.   begin
  254.     Fname1 := FExpand( ParamStr( 1 ) );
  255.     Fname2 := FExpand( ParamStr( 2 ) );
  256.     tel := 0;
  257.     if FileExist( Fname1 ) then
  258.     begin
  259.       if OpenTextFile( OldFile, Fname1, OldBuf ) then
  260.       begin
  261.         if CreateTextFile( NewFile, Fname2, NewBuf ) then
  262.         begin
  263.           ReadLn( OldFile, Line1 );
  264.  
  265.           if not Eof( OldFile ) and ( IOResult = 0 ) then
  266.           begin
  267.             TestLine( Line1, tmp1 );
  268.             if length( Line1 ) > 0 then
  269.             begin
  270.               WriteLn( NewFile, Line1 );
  271.               tel := 1;
  272.             end;
  273.             ReadLn( OldFile, Line2 );
  274.           end;
  275.  
  276.           while not Eof( OldFile ) and ( IOResult = 0 ) do
  277.           begin
  278.             TestLine( Line2, tmp2 );
  279.             if (length( Line2 ) > 0) and (tmp1 <> tmp2) then
  280.             begin
  281.               StrCopy( Line2, Line1 );         { copy Line2 to Line1 }
  282.               StrCopy( tmp2, tmp1 );           { copy tmp2  to tmp1  }
  283.               WriteLn( NewFile, Line1 );
  284.               inc( tel );
  285.             end;
  286.             ReadLn( OldFile, Line2 );
  287.           end {while not eof};
  288.  
  289.           TestLine( Line2, tmp2 );
  290.           if (length( Line2 ) > 0) and (tmp1 <> tmp2) then
  291.           begin
  292.             WriteLn( NewFile, Line2 );
  293.             inc( tel );
  294.           end;
  295.  
  296.           writeln (tel, ' unique lines');
  297.           Close( NewFile );
  298.           Close( OldFile );
  299.         end { if create file2 }
  300.         else
  301.           writeln(' error creating file ', Fname1 );
  302.         { error creating file }
  303.       end { if open file1 }
  304.       else
  305.         writeln(' error opening file ', Fname1 );
  306.       { error opening file }
  307.     end { if FileExist( Fname1 ) }
  308.     else
  309.       writeln( Fname1, ' not found' );
  310.     { file not found }
  311.   end { if ParamCount > 1 }
  312.   else
  313.     Writeln( 'Dup file1 file2' );
  314. end.
  315.